use std::collections::HashMap;
use std::path::Path;
use std::sync::Arc;
use calamine::{Reader, Xlsx, open_workbook};
use serde::{Deserialize, Serialize};
use tokio::sync::RwLock;
use notify::{Watcher, RecursiveMode, recommended_watcher, Event};
use tokio::sync::mpsc;
use tracing::{info, warn, error};

use crate::error::{Result, ModbusCollectorError};

/// 设备配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceConfig {
    pub device_id: String,
    pub device_name: String,
    pub protocol: ProtocolType,
    pub connection: String,
    pub slave_id: u8,
    pub timeout: u64,
    pub interval: u64,
    pub enable: bool,
}

/// 协议类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ProtocolType {
    ModbusTcp,
    ModbusRtu,
}

/// 点位配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PointConfig {
    pub point_id: String,
    pub device_id: String,
    pub name: String,
    pub address: u32,
    pub data_type: DataType,
    pub operation: Option<String>,
    pub byte_order: ByteOrder,
    pub is_historical: bool,
    pub is_monitored: bool,
}

/// 数据类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DataType {
    Int16,
    UInt16,
    Int32,
    UInt32,
    Float32,
    Float64,
    Bool,
}

/// 字节序
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ByteOrder {
    Abcd, // 大端
    Dcba, // 小端
    Badc, // 中间字节交换
    Cdab, // 字节对交换
}

/// 写入配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WriteConfig {
    pub point_id: String,
    pub write_function: u8,
    pub access_level: String,
    pub min_value: f64,
    pub max_value: f64,
}

/// 配置管理器
#[derive(Debug, Clone)]
pub struct ConfigManager {
    file_path: String,
    devices: Arc<RwLock<HashMap<String, DeviceConfig>>>,
    points: Arc<RwLock<HashMap<String, PointConfig>>>,
    writes: Arc<RwLock<HashMap<String, WriteConfig>>>,
}

impl ConfigManager {
    pub async fn new(file_path: &str) -> Result<Self> {
        let manager = Self {
            file_path: file_path.to_string(),
            devices: Arc::new(RwLock::new(HashMap::new())),
            points: Arc::new(RwLock::new(HashMap::new())),
            writes: Arc::new(RwLock::new(HashMap::new())),
        };
        
        // 加载配置
        manager.load_config().await?;
        
        // 启动文件监控
        manager.start_file_watcher().await?;
        
        Ok(manager)
    }
    
    /// 加载Excel配置文件
    async fn load_config(&self) -> Result<()> {
        info!("Loading configuration from: {}", self.file_path);
        
        let mut workbook: Xlsx<_> = open_workbook(&self.file_path)?;
        
        // 加载设备配置
        self.load_devices(&mut workbook).await?;
        
        // 加载点位配置
        self.load_points(&mut workbook).await?;
        
        // 加载写入配置
        self.load_writes(&mut workbook).await?;
        
        info!("Configuration loaded successfully");
        Ok(())
    }
    
    /// 加载设备配置
    async fn load_devices(&self, workbook: &mut Xlsx<std::io::BufReader<std::fs::File>>) -> Result<()> {
        let range = workbook.worksheet_range("Device")
            .map_err(|e| ModbusCollectorError::Config(format!("Device sheet not found: {}", e)))?;
        
        let mut devices = HashMap::new();
        
        // 跳过标题行
        for row in range.rows().skip(1) {
            if row.len() < 8 {
                continue;
            }
            
            let device_id = row[0].get_string().unwrap_or_default().to_string();
            if device_id.is_empty() {
                continue;
            }
            
            let protocol = match row[2].get_string().unwrap_or_default() {
                "MODBUS_TCP" => ProtocolType::ModbusTcp,
                "MODBUS_RTU" => ProtocolType::ModbusRtu,
                _ => {
                    warn!("Unknown protocol for device {}, skipping", device_id);
                    continue;
                }
            };
            
            let device = DeviceConfig {
                device_id: device_id.clone(),
                device_name: row[1].get_string().unwrap_or_default().to_string(),
                protocol,
                connection: row[3].get_string().unwrap_or_default().to_string(),
                slave_id: row[4].get_float().unwrap_or(1.0) as u8,
                timeout: row[5].get_float().unwrap_or(3000.0) as u64,
                interval: row[6].get_float().unwrap_or(5000.0) as u64,
                enable: row[7].get_string().unwrap_or("FALSE").to_uppercase() == "TRUE",
            };
            
            devices.insert(device_id, device);
        }
        
        *self.devices.write().await = devices;
        info!("Loaded {} devices", self.devices.read().await.len());
        Ok(())
    }
    
    /// 加载点位配置
    async fn load_points(&self, workbook: &mut Xlsx<std::io::BufReader<std::fs::File>>) -> Result<()> {
        let range = workbook.worksheet_range("Point")
            .map_err(|e| ModbusCollectorError::Config(format!("Point sheet not found: {}", e)))?;
        
        let mut points = HashMap::new();
        
        for row in range.rows().skip(1) {
            if row.len() < 9 {
                continue;
            }
            
            let point_id = row[0].get_string().unwrap_or_default().to_string();
            if point_id.is_empty() {
                continue;
            }
            
            let data_type = match row[4].get_string().unwrap_or_default() {
                "INT16" => DataType::Int16,
                "UINT16" => DataType::UInt16,
                "INT32" => DataType::Int32,
                "UINT32" => DataType::UInt32,
                "FLOAT32" => DataType::Float32,
                "FLOAT64" => DataType::Float64,
                "BOOL" => DataType::Bool,
                _ => {
                    warn!("Unknown data type for point {}, defaulting to UINT16", point_id);
                    DataType::UInt16
                }
            };
            
            let byte_order = match row[6].get_string().unwrap_or("ABCD") {
                "ABCD" => ByteOrder::Abcd,
                "DCBA" => ByteOrder::Dcba,
                "BADC" => ByteOrder::Badc,
                "CDAB" => ByteOrder::Cdab,
                _ => ByteOrder::Abcd,
            };
            
            let point = PointConfig {
                point_id: point_id.clone(),
                device_id: row[1].get_string().unwrap_or_default().to_string(),
                name: row[2].get_string().unwrap_or_default().to_string(),
                address: row[3].get_float().unwrap_or(0.0) as u32,
                data_type,
                operation: {
                    let op = row[5].get_string().unwrap_or_default();
                    if op.is_empty() { None } else { Some(op.to_string()) }
                },
                byte_order,
                is_historical: row[7].get_string().unwrap_or("FALSE").to_uppercase() == "TRUE",
                is_monitored: row[8].get_string().unwrap_or("FALSE").to_uppercase() == "TRUE",
            };
            
            points.insert(point_id, point);
        }
        
        *self.points.write().await = points;
        info!("Loaded {} points", self.points.read().await.len());
        Ok(())
    }
    
    /// 加载写入配置
    async fn load_writes(&self, workbook: &mut Xlsx<std::io::BufReader<std::fs::File>>) -> Result<()> {
        // 写入配置表是可选的
        if let Ok(range) = workbook.worksheet_range("Write") {
            let mut writes = HashMap::new();
            
            for row in range.rows().skip(1) {
                if row.len() < 5 {
                    continue;
                }
                
                let point_id = row[0].get_string().unwrap_or_default().to_string();
                if point_id.is_empty() {
                    continue;
                }
                
                let write = WriteConfig {
                    point_id: point_id.clone(),
                    write_function: row[1].get_string().unwrap_or("06")
                        .parse::<u8>().unwrap_or(6),
                    access_level: row[2].get_string().unwrap_or("admin").to_string(),
                    min_value: row[3].get_float().unwrap_or(0.0),
                    max_value: row[4].get_float().unwrap_or(100.0),
                };
                
                writes.insert(point_id, write);
            }
            
            *self.writes.write().await = writes;
            info!("Loaded {} write configurations", self.writes.read().await.len());
        } else {
            warn!("Write sheet not found, write operations will be disabled");
        }
        
        Ok(())
    }
    
    /// 启动文件监控
    async fn start_file_watcher(&self) -> Result<()> {
        let (tx, mut rx) = mpsc::channel(1);
        let file_path = self.file_path.clone();
        let config_manager = self.clone();
        
        // 创建文件监控器
        let mut watcher = recommended_watcher(move |res: notify::Result<Event>| {
            if let Ok(event) = res {
                if event.kind.is_modify() {
                    if let Err(e) = tx.blocking_send(()) {
                        error!("Failed to send file change notification: {}", e);
                    }
                }
            }
        })?;
        
        // 监控配置文件
        watcher.watch(Path::new(&file_path), RecursiveMode::NonRecursive)?;
        
        // 启动监控任务
        tokio::spawn(async move {
            while let Some(_) = rx.recv().await {
                info!("Configuration file changed, reloading...");
                if let Err(e) = config_manager.load_config().await {
                    error!("Failed to reload configuration: {}", e);
                } else {
                    info!("Configuration reloaded successfully");
                }
                
                // 防止频繁重载
                tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
            }
        });
        
        // 保持监控器活着
        std::mem::forget(watcher);
        
        Ok(())
    }
    
    /// 获取所有设备配置
    pub async fn get_devices(&self) -> HashMap<String, DeviceConfig> {
        self.devices.read().await.clone()
    }
    
    /// 获取特定设备配置
    pub async fn get_device(&self, device_id: &str) -> Option<DeviceConfig> {
        self.devices.read().await.get(device_id).cloned()
    }
    
    /// 获取所有点位配置
    pub async fn get_points(&self) -> HashMap<String, PointConfig> {
        self.points.read().await.clone()
    }
    
    /// 获取特定设备的点位配置
    pub async fn get_device_points(&self, device_id: &str) -> Vec<PointConfig> {
        self.points.read().await.values()
            .filter(|p| p.device_id == device_id)
            .cloned()
            .collect()
    }
    
    /// 获取特定点位配置
    pub async fn get_point(&self, point_id: &str) -> Option<PointConfig> {
        self.points.read().await.get(point_id).cloned()
    }
    
    /// 获取所有写入配置
    pub async fn get_writes(&self) -> HashMap<String, WriteConfig> {
        self.writes.read().await.clone()
    }
    
    /// 获取特定点位的写入配置
    pub async fn get_write_config(&self, point_id: &str) -> Option<WriteConfig> {
        self.writes.read().await.get(point_id).cloned()
    }
}